#include "MyIO.h"

#include <string.h>
#include "MyAssert.h"

#include "LogInterface.h"

#define IO_BUFFER_MAX_SIZE 16*1024

COutput Output;
CIOStreamEndl Endl;


CIOStream::CIOStream()
{
	m_pBuffer = new char[IO_BUFFER_MAX_SIZE];
	Assert(m_pBuffer);
}

CIOStream::~CIOStream()
{
	if(m_pBuffer)
	{
		delete[] m_pBuffer;
		m_pBuffer = NULL;
	}
}

#define PUT_DATA_INTO_BUFFER(fmt,a) \
	m_Mutex.Lock();	\
	if(m_CurPos >= IO_BUFFER_MAX_SIZE - 256)	\
	{ \
		m_Mutex.Unlock();	\
		Flush();	\
		m_Mutex.Lock();	\
	}	\
	sprintf(m_pBuffer + m_CurPos,fmt,a);	\
	m_CurPos = strlen(m_pBuffer);	\
	m_Mutex.Unlock();	\
	return *this

CIOStream& CIOStream::operator <<(char a)
{
	PUT_DATA_INTO_BUFFER("%d",a);
}

CIOStream& CIOStream::operator <<(UInt8 a)
{
	PUT_DATA_INTO_BUFFER("%u",a);
}

CIOStream& CIOStream::operator <<(Int16 a)
{
	PUT_DATA_INTO_BUFFER("%d",a);
}

CIOStream& CIOStream::operator <<(UInt16 a)
{
	PUT_DATA_INTO_BUFFER("%u",a);
}

CIOStream& CIOStream::operator <<(Int32 a)
{
	PUT_DATA_INTO_BUFFER("%d",a);
}

CIOStream& CIOStream::operator <<(UInt32 a)
{
	PUT_DATA_INTO_BUFFER("%u",a);
}

CIOStream& CIOStream::operator <<(Int64 a)
{
#ifdef WIN32
	PUT_DATA_INTO_BUFFER("%I64d",a);
#else
	PUT_DATA_INTO_BUFFER("%lld",a);
#endif
}

CIOStream& CIOStream::operator <<(UInt64 a)
{
#ifdef WIN32
	PUT_DATA_INTO_BUFFER("%I64u",a);
#else
	PUT_DATA_INTO_BUFFER("%llu",a);
#endif
}

CIOStream& CIOStream::operator <<(Float32 a)
{
	PUT_DATA_INTO_BUFFER("%f",a);
}

CIOStream& CIOStream::operator <<(const char *pData)
{
	UInt32 iLen = strlen(pData);
	if(iLen > IO_BUFFER_MAX_SIZE - 256)
	{
		Assert(FALSE);
		return *this;
	}

	m_Mutex.Lock();
	if(iLen + m_CurPos > IO_BUFFER_MAX_SIZE - 256)
	{
		m_Mutex.Unlock();
		Flush();
		m_Mutex.Lock();
	}
	m_Mutex.Unlock();
	
	PUT_DATA_INTO_BUFFER("%s",pData);
}

CIOStream& CIOStream::operator <<(CIOStream & data)
{
	return CIOStream::operator<<(data.GetBuffer());
}

CIOStream& CIOStream::operator <<(CIOStreamEndl &a)
{
	CIOStream::operator<<("\n");
	Flush();
	return *this;
}

const char* CIOStream::GetBuffer()
{
	return m_pBuffer;
}

void CIOStream::Reset()
{
	m_CurPos = 0;
	m_pBuffer[m_CurPos] = 0;
}

void CIOStream::Flush()
{
	m_Mutex.Lock();
	Reset();
	m_Mutex.Unlock();
}


COutput::COutput()
{
}

COutput::~COutput()
{
}

void COutput::Flush()
{
	m_Mutex.Lock();
	if(m_CurPos > 0)
	{
		fprintf(stdout,"%s",GetBuffer());
		OutputDebugString(GetBuffer());
		Reset();
	}
	m_Mutex.Unlock();
}


CDumpToFile::CDumpToFile(const char *pFile, Bool isOverride)
: CIOStream()
{
	m_pFile = fopen(pFile, isOverride ? "w" : "w+");
}

CDumpToFile::~CDumpToFile()
{
	if(m_pFile)
	{
		fclose(m_pFile);
		m_pFile = NULL;
	}
}

void CDumpToFile::Flush()
{
	m_Mutex.Lock();
	if(m_CurPos > 0)
	{
		if(m_pFile)
			fprintf(m_pFile,"%s",GetBuffer());

		Reset();
	}
	m_Mutex.Unlock();
}

